﻿#region

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using NetBay.Core.BusinessEntities;
using Rio.Framework.Localisation;
using Rio.Framework.Pages.Context;
using Rio.Framework.Pages.Helpers;
using Rio.Framework.Pages.Helpers.Comparer;
using Telerik.Windows.Controls;
using WindowStartupLocation = Telerik.Windows.Controls.WindowStartupLocation;

#endregion

namespace Rio.Framework.Pages.ChildWindows
{
    /// <summary>
    ///   Folder right for administrator
    /// </summary>
    public partial class FolderAdministrationWindow : RadWindow
    {
        #region Readonly & Static Fields

        private readonly User m_oDefaultAllUser = new User(); // User representing everybody
        private readonly Folder m_oFolderSelected; // Selected Folder
        private readonly FolderType m_oFolderTypeSelected; // Selected Folder Type

        private readonly UserComparer m_oUserComparer = new UserComparer(); // User comparer

        private readonly List<long> m_oUserIdAdmin = new List<long>();

        private readonly TextBlock m_oWaitingMessage = new TextBlock
                                                           {
                                                               FontSize = 18,
                                                               HorizontalAlignment = HorizontalAlignment.Center,
                                                               VerticalAlignment = VerticalAlignment.Center,
                                                               Foreground = new SolidColorBrush(Colors.Black)
                                                           };

        #endregion

        #region Fields

        private bool m_bActivateKeyDown;
        private int m_iNbrUserAvaillable; // Number of users availlable

        private string m_sLabelCancelMessage;
        private string m_sLabelCantMoveUserMessage;
        private string m_sLabelValidationMessage;

        #endregion

        #region Constructors

        public FolderAdministrationWindow()
        {
            InitializeComponent();

            CanMove = false;
            ResizeMode = ResizeMode.NoResize;
            WindowStartupLocation = WindowStartupLocation.CenterScreen;

            foreach (UIElement L_oUIE in LayoutRoot.Children)
            {
                L_oUIE.Visibility = Visibility.Collapsed;
            }
            Grid.SetColumnSpan(m_oWaitingMessage, 3);
            Grid.SetRowSpan(m_oWaitingMessage, 3);
            LayoutRoot.Children.Add(m_oWaitingMessage);
        }


        public FolderAdministrationWindow(FolderType P_oFolderTypeSelected, Folder P_oFolderSelected)
            : this()
        {
            // Initialization 
            m_oFolderTypeSelected = P_oFolderTypeSelected;
            m_oFolderSelected = P_oFolderSelected;

            // Initialization of labels
            InitLabel();

            // Get user availlable from base and bind it to ListBox
            GetUsersAvaillable();
        }

        #endregion

        #region Instance Methods

        /// <summary>
        ///   Translation
        /// </summary>
        public void InitLabel()
        {
            UsersAvaillableTextBlock.Text = String.Format(Resx.GetLabel(ResxFolderAdministration.USER_AVAILLABLE), m_oFolderTypeSelected.Label);
            UsersSelectedTextBlock.Text = Resx.GetLabel(ResxFolderAdministration.USER_HAVING_RIGHT);

            OkButton.Content = Resx.GetLabel(ResxFolderAdministration.VALIDATION);
            CancelButton.Content = Resx.GetLabel(ResxAlert.CANCEL);

            GoToRigthButton.SetValue(ToolTipService.ToolTipProperty, Resx.GetLabel(ResxFolderAdministration.MOVE_TO_RIGHT));
            GoToLeftButton.SetValue(ToolTipService.ToolTipProperty, Resx.GetLabel(ResxFolderAdministration.MOVE_TO_LEFT));

            m_sLabelCancelMessage = Resx.GetLabel(ResxFolderAdministration.CANCEL_MESSAGE);
            m_sLabelValidationMessage = Resx.GetLabel(ResxFolderAdministration.VALIDATION_MESSAGE);
            m_sLabelCantMoveUserMessage = Resx.GetLabel(ResxFolderAdministration.CANTMOVE_MESSAGE);

            m_oWaitingMessage.Text = Resx.GetLabel(ResxCommon.SPLASHSCREEN_MESSAGE);

            m_oDefaultAllUser.FullName = Resx.GetLabel(ResxFolderAdministration.EVERYBODY);
            m_oDefaultAllUser.UserId = -1;
        }

        private void CloseFolderAdminWindow()
        {
            MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow("", m_sLabelCancelMessage, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
            L_oMessage.Show();
            L_oMessage.Closed += (s, ev) =>
                                     {
                                         if (L_oMessage.Result == MessageBoxResult.Yes)
                                         {
                                             DialogResult = false;
                                             Close();
                                         }
                                         else
                                         {
                                             Focus();
                                         }
                                     };
        }

        /// <summary>
        ///   Get user availlable from base and bind it to ListBox
        /// </summary>
        private void GetUsersAvaillable()
        {
            try
            {
                var query = GlobalWebContext.BusinessEntitiesDomainContext.GetUsersByFolderTypeIdQuery(
                    m_oFolderTypeSelected.Identifier
                    );
                GlobalWebContext.BusinessEntitiesDomainContext.Load(query, OnGetUsersByFolderTypeIdQueryCallback, null);
            }
            catch (Exception)
            {
                //Logger.Write("EXCEPTION : " + Environment.NewLine + ex, Logger.Level.Error);
            }
        }

        // Bind result query

        /// <summary>
        ///   Get user who have right from base and bind it to ListBox
        /// </summary>
        private void GetUsersSelected()
        {
            try
            {
                var query = GlobalWebContext.BusinessEntitiesDomainContext.GetUsersByFolderIdQuery(
                    m_oFolderSelected.Iddoc
                    );
                GlobalWebContext.BusinessEntitiesDomainContext.Load(query, OnGetUsersByFolderIdQueryCallback, null);
            }
            catch (Exception)
            {
                //Logger.Write("EXCEPTION : " + Environment.NewLine + ex, Logger.Level.Error);
            }
        }

        // Bind result query

        private void GoToLeftEventAsked()
        {
            if (ListBoxUsersSelected.SelectedItems.Count > 0)
            {
                List<User> L_oAdminIdSelected = new List<User>();

                for (int i = 0; i < ListBoxUsersSelected.SelectedItems.Count; i++)
                {
                    User l_oUser = (User) ListBoxUsersSelected.SelectedItems[i];
                    if (m_oUserIdAdmin.Contains(l_oUser.UserId))
                    {
                        L_oAdminIdSelected.Add(l_oUser);
                    }
                    else
                    {
                        ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Add(l_oUser);
                        ((ObservableCollection<User>) ListBoxUsersSelected.ItemsSource).Remove(l_oUser);
                    }
                }

                if (L_oAdminIdSelected.Count > 0)
                {
                    string L_sUserFullNameConcat = String.Empty;
                    foreach (User L_oUserAdminToConcat in L_oAdminIdSelected)
                    {
                        L_sUserFullNameConcat += L_oUserAdminToConcat.FullName + ", ";
                    }
                    L_sUserFullNameConcat.Substring(0, L_sUserFullNameConcat.Length - 1);
                    string L_sMessageToDisplay = String.Format(m_sLabelCantMoveUserMessage, L_sUserFullNameConcat, m_oFolderTypeSelected.Label);
                    MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow("", L_sMessageToDisplay, MessageBoxButtons.Ok, MessageBoxIcon.Warning);
                    L_oMessage.Show();
                    L_oMessage.Closed += (s, ev) =>
                                             {
                                                 Focus();
                                                 ListBoxUsersSelected.ItemsSource =
                                                     new ObservableCollection<User>(((ObservableCollection<User>) ListBoxUsersSelected.ItemsSource).OrderBy(x => x.FullName).ToList());
                                                 ListBoxUsersAvaillable.ItemsSource =
                                                     new ObservableCollection<User>(((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).OrderBy(x => x.FullName).ToList());
                                             };
                }
            }
        }

        private void GoToRightEventAsked()
        {
            if (ListBoxUsersAvaillable.SelectedItems.Count > 0)
            {
                for (int i = 0; i < ListBoxUsersAvaillable.SelectedItems.Count; i++)
                {
                    User l_oUser = (User) ListBoxUsersAvaillable.SelectedItems[i];
                    ((ObservableCollection<User>) ListBoxUsersSelected.ItemsSource).Add(l_oUser);
                    ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Remove(l_oUser);
                }
                ListBoxUsersSelected.ItemsSource = new ObservableCollection<User>(((ObservableCollection<User>) ListBoxUsersSelected.ItemsSource).OrderBy(x => x.FullName).ToList());
                ListBoxUsersAvaillable.ItemsSource = new ObservableCollection<User>(((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).OrderBy(x => x.FullName).ToList());
            }
        }

        private void OnGetUsersByFolderIdQueryCallback(LoadOperation<User> result)
        {
            ObservableCollection<User> L_oUserSelected = new ObservableCollection<User>(result.Entities);
            ObservableCollection<User> L_oSearchSelectedUserInAvaillable = new ObservableCollection<User>();


            // If No entries in table everybody have right
            if (L_oUserSelected.Count == 0)
            {
                foreach (User L_oUser in (ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource)
                {
                    L_oSearchSelectedUserInAvaillable.Add(L_oUser);
                }
                ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Clear();
            }
            else
            {
                List<User> L_oUserToRemoveFromSelected = new List<User>();

                // Check if user result have right on foldertype
                foreach (User L_oUserResult in L_oUserSelected)
                {
                    if (!((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Contains(L_oUserResult, m_oUserComparer))
                    {
                        L_oUserToRemoveFromSelected.Add(L_oUserResult);
                    }
                }

                foreach (User L_oUserToRemove in L_oUserToRemoveFromSelected)
                {
                    L_oUserSelected.Remove(L_oUserSelected.Where(x => x.UserId == L_oUserToRemove.UserId).FirstOrDefault());
                }

                if (((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Count == L_oUserSelected.Count)
                {
                    foreach (User L_oUser in (ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource)
                    {
                        L_oSearchSelectedUserInAvaillable.Add(L_oUser);
                    }
                    ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Clear();
                }
                else
                {
                    foreach (User L_oUserSearch in L_oUserSelected)
                    {
                        User L_oUserSearchToAdd = ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Where(x => x.UserId == L_oUserSearch.UserId).FirstOrDefault();
                        L_oSearchSelectedUserInAvaillable.Add(L_oUserSearchToAdd);
                    }
                }

                foreach (User L_oUserToRemove in L_oUserSelected)
                {
                    ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Remove(
                        ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource).Where(x => x.UserId == L_oUserToRemove.UserId).FirstOrDefault());
                }
            }

            L_oSearchSelectedUserInAvaillable.OrderBy(x => x.FullName);
            ListBoxUsersSelected.ItemsSource = L_oSearchSelectedUserInAvaillable;
            ListBoxUsersSelected.DisplayMemberPath = "FullName";

            foreach (UIElement L_oUIE in LayoutRoot.Children)
            {
                L_oUIE.Visibility = Visibility.Visible;
            }
            m_oWaitingMessage.Visibility = Visibility.Collapsed;
            m_bActivateKeyDown = true;
        }

        private void OnGetUsersByFolderTypeIdQueryCallback(LoadOperation<User> result)
        {
            ObservableCollection<User> L_oUsersAvaillable = new ObservableCollection<User>(result.Entities);
            L_oUsersAvaillable = new ObservableCollection<User>(L_oUsersAvaillable.OrderBy(x => x.FullName).ToList());

            FolderTypeComparer L_oFolderTypeComparer = new FolderTypeComparer();
            foreach (User L_oUserM in L_oUsersAvaillable)
            {
                foreach (Group L_oUserGroup in L_oUserM.GroupList)
                {
                    if ((L_oUserGroup.IsAdministrator) && (L_oUserGroup.FolderTypeRigthList.Contains(m_oFolderTypeSelected, L_oFolderTypeComparer)))
                    {
                        m_oUserIdAdmin.Add(L_oUserM.UserId);
                        break;
                    }
                }
            }

            ListBoxUsersAvaillable.ItemsSource = L_oUsersAvaillable;
            m_iNbrUserAvaillable = L_oUsersAvaillable.Count;
            // Display FullName
            ListBoxUsersAvaillable.DisplayMemberPath = "FullName";

            // Get user who have right from base and bind it to ListBox
            GetUsersSelected();
        }

        // Validation on base

        private void SetRight()
        {
            List<long> l_oUserToAddRightList = new List<long>();
            List<long> l_oUserToDeleteRightList = new List<long>();

            try
            {
                foreach (User L_oUserSelected in ((ObservableCollection<User>) ListBoxUsersSelected.ItemsSource))
                {
                    l_oUserToAddRightList.Add(L_oUserSelected.UserId);
                }

                foreach (User L_oUserSelected in ((ObservableCollection<User>) ListBoxUsersAvaillable.ItemsSource))
                {
                    l_oUserToDeleteRightList.Add(L_oUserSelected.UserId);
                }

                if (l_oUserToDeleteRightList.Count == 0)
                {
                    GlobalWebContext.BusinessEntitiesDomainContext.DeleteAuthorisationsDoc(m_oFolderSelected.Iddoc, l_oUserToAddRightList, m_oFolderSelected.Identifier,
                                                                                           m_oFolderTypeSelected.Identifier);
                }
                else
                {
                    GlobalWebContext.BusinessEntitiesDomainContext.DeleteAuthorisationsDoc(m_oFolderSelected.Iddoc, l_oUserToDeleteRightList, m_oFolderSelected.Identifier,
                                                                                           m_oFolderTypeSelected.Identifier);
                    GlobalWebContext.BusinessEntitiesDomainContext.AddAuthorisationsDoc(m_oFolderSelected.Iddoc, l_oUserToAddRightList, m_oFolderSelected.Identifier, m_oFolderTypeSelected.Identifier);
                }
            }
            catch (Exception)
            {
                //Logger.Write("EXCEPTION : " + Environment.NewLine + ex, Logger.Level.Error);
            }
        }

        private void ValidateFolderAdministration()
        {
            MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow("", m_sLabelValidationMessage, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
            L_oMessage.Show();
            L_oMessage.Closed += (s, ev) =>
                                     {
                                         if (L_oMessage.Result == MessageBoxResult.Yes)
                                         {
                                             SetRight();
                                             DialogResult = true;
                                             Close();
                                         }
                                         else
                                         {
                                             Focus();
                                         }
                                     };
        }

        #endregion

        #region Event Handling

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            CloseFolderAdminWindow();
        }

        private void ChildWindow_KeyDown(object sender, KeyEventArgs e)
        {
            if (m_bActivateKeyDown)
            {
                switch (e.Key)
                {
                    case Key.Escape:
                        {
                            CloseFolderAdminWindow();
                            break;
                        }
                    case Key.Enter:
                        {
                            ValidateFolderAdministration();
                            break;
                        }
                }
            }
        }

        private void GoToLeftButton_Click(object sender, RoutedEventArgs e)
        {
            GoToLeftEventAsked();
        }

        private void GoToRigthButton_Click(object sender, RoutedEventArgs e)
        {
            GoToRightEventAsked();
        }

        private void ListBoxUsersAvaillable_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                GoToRightEventAsked();
            }
        }

        private void ListBoxUsersSelected_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                GoToLeftEventAsked();
            }
        }

        private void OkButton_Click(object sender, RoutedEventArgs e)
        {
            ValidateFolderAdministration();
        }

        #endregion
    }
}